home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / dpmigcc5.zip / RSX / SOURCE / FPU-EMU / POLYNOMI.S < prev    next >
Text File  |  1994-05-27  |  4KB  |  142 lines

  1. /*---------------------------------------------------------------------------+
  2.  |  polynomial.S                                                             |
  3.  |                                                                           |
  4.  | Fixed point arithmetic polynomial evaluation.                             |
  5.  |                                                                           |
  6.  | Copyright (C) 1992,1993                                                   |
  7.  |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
  8.  |                       Australia.  E-mail   billm@vaxc.cc.monash.edu.au    |
  9.  |                                                                           |
  10.  | Call from C as:                                                           |
  11.  |   void polynomial(unsigned accum[], unsigned x[], unsigned terms[][2],    |
  12.  |                   int n)                                                  |
  13.  |                                                                           |
  14.  | Computes:                                                                 |
  15.  | terms[0] + (terms[1] + (terms[2] + ... + (terms[n-1]*x)*x)*x)*x) ... )*x  |
  16.  | The result is returned in accum.                                          |
  17.  |                                                                           |
  18.  +---------------------------------------------------------------------------*/
  19.  
  20.     .file    "fpolynom.s"
  21.  
  22. #include "fpu_asm.h"
  23.  
  24.  
  25. /*    #define    EXTRA_PRECISE    // Do not use: not complete */
  26.  
  27. #define    TERM_SIZE    $8
  28. #define    SUM_MS        -20(%ebp)    /* sum ms long */
  29. #define SUM_MIDDLE    -24(%ebp)    /* sum middle long */
  30. #define    SUM_LS        -28(%ebp)    /* sum ls long */
  31. #define    SUM_LS_HI    -25(%ebp)    /* high byte of sum ls */
  32. #define    ACCUM_MS    -4(%ebp)    /* accum ms long */
  33. #define    ACCUM_MIDDLE    -8(%ebp)    /* accum middle long */
  34. #define    ACCUM_LS    -12(%ebp)    /* accum ls long */
  35. #define ACCUM_LS_HI    -9(%ebp)    /* high byte of accum ls */
  36.  
  37. .text
  38.     .align 2,144
  39. .globl _polynomial
  40. _polynomial:
  41.     pushl    %ebp
  42.     movl    %esp,%ebp
  43.     subl    $32,%esp
  44.     pushl    %esi
  45.     pushl    %edi
  46.     pushl    %ebx
  47.  
  48.     movl    PARAM2,%esi        /* x */
  49.     movl    PARAM3,%edi        /* terms */
  50.  
  51.     movl    TERM_SIZE,%eax
  52.     mull    PARAM4            /* n */
  53.     addl    %eax,%edi
  54.  
  55.     movl    4(%edi),%edx        /* terms[n] */
  56.     movl    %edx,SUM_MS
  57.     movl    (%edi),%edx        /* terms[n] */
  58.     movl    %edx,SUM_MIDDLE
  59.     xor    %eax,%eax
  60.     movl    %eax,SUM_LS
  61.  
  62.     subl    TERM_SIZE,%edi
  63.     decl    PARAM4
  64.     js    L_accum_done
  65.  
  66. L_accum_loop:
  67.     xor    %eax,%eax
  68.     movl    %eax,ACCUM_MS
  69.     movl    %eax,ACCUM_MIDDLE
  70.  
  71.     movl    SUM_MIDDLE,%eax
  72.     mull    (%esi)            /* x ls long */
  73. /*    movl    %eax,-16(%ebp)        // Not needed */
  74.     movl    %edx,ACCUM_LS
  75.  
  76.     movl    SUM_MIDDLE,%eax
  77.     mull    4(%esi)            /* x ms long */
  78.     addl    %eax,ACCUM_LS
  79.     adcl    %edx,ACCUM_MIDDLE
  80.     adcl    $0,ACCUM_MS
  81.  
  82.     movl    SUM_MS,%eax
  83.     mull    (%esi)            /* x ls long */
  84.     addl    %eax,ACCUM_LS
  85.     adcl    %edx,ACCUM_MIDDLE
  86.     adcl    $0,ACCUM_MS
  87.  
  88.     movl    SUM_MS,%eax
  89.     mull    4(%esi)            /* x ms long */
  90.     addl    %eax,ACCUM_MIDDLE
  91.     adcl    %edx,ACCUM_MS
  92.  
  93. /*
  94.  * Now put the sum of next term and the accumulator
  95.  * into the sum register
  96.  */
  97.     movl    ACCUM_MIDDLE,%eax
  98.     addl    (%edi),%eax        /* term ls long */
  99.     movl    %eax,SUM_MIDDLE
  100.     movl    ACCUM_MS,%eax
  101.     adcl    4(%edi),%eax        /* term ms long */
  102.     movl    %eax,SUM_MS
  103.  
  104. #ifdef EXTRA_PRECISE
  105.     movl    ACCUM_LS,%eax
  106.     movl    %eax,SUM_LS
  107. #else
  108.     testb    $0x80,ACCUM_LS_HI    /* ms bit of ACCUM_LS */
  109.     je    L_no_poly_round
  110.  
  111.     addl    $1,SUM_MIDDLE
  112.     adcl    $0,SUM_MS
  113. L_no_poly_round:
  114. #endif EXTRA_PRECISE
  115.  
  116.     subl    TERM_SIZE,%edi
  117.     decl    PARAM4
  118.     jns    L_accum_loop
  119.  
  120. L_accum_done:
  121. #ifdef EXTRA_PRECISE
  122. /* Round the result */
  123.     testb    $128,SUM_LS_HI
  124.     je    L_poly_done
  125.  
  126.     addl    $1,SUM_MIDDLE
  127.     adcl    $0,SUM_MS
  128. #endif EXTRA_PRECISE
  129.  
  130. L_poly_done:
  131.     movl    PARAM1,%edi        /* accum */
  132.     movl    SUM_MIDDLE,%eax
  133.     movl    %eax,(%edi)
  134.     movl    SUM_MS,%eax
  135.     movl    %eax,4(%edi)
  136.  
  137.     popl    %ebx
  138.     popl    %edi
  139.     popl    %esi
  140.     leave
  141.     ret
  142.